package com.gjd.service.impl;

import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gjd.domain.ResponseResult;
import com.gjd.domain.dto.CodeDto;
import com.gjd.domain.dto.EmailDto;
import com.gjd.domain.entity.Admin;
import com.gjd.domain.entity.CodeObject;
import com.gjd.domain.entity.LoginAdmin;
import com.gjd.domain.vo.AdminInfoVo;
import com.gjd.domain.vo.AdminLoginVo;
import com.gjd.domain.vo.enums.AppHttpCodeEnum;
import com.gjd.handler.CodeAuthenticationHandle;
import com.gjd.mapper.AdminMapper;
import com.gjd.service.AdminLoginService;
import com.gjd.service.EmailService;
import com.gjd.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.Objects;
import java.util.concurrent.TimeUnit;


@Service
public class AdminLoginServiceImpl implements AdminLoginService {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private AdminMapper adminMapper;

    @Autowired
    private EmailService emailService;

    @Autowired
    private CodeAuthenticationHandle codeAuthHandle;

    final String content = "您好，您的验证码为";

    @Override
    public ResponseResult login(Admin admin) {
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(admin.getUserName(), admin.getPassword());
//        Authentication会调用重写后的UserDetailsServiceImpl
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);

//        判断是否认证通过
        if (Objects.isNull(authenticate)) {
            throw new RuntimeException("用户名或密码错误");
        }

//        获取userid,生成token
        LoginAdmin LoginAdmin = (LoginAdmin) authenticate.getPrincipal();
        String adminId = String.valueOf(LoginAdmin.getAdmin().getId());
        String jwt = JwtUtil.createJWT(adminId);

        //把用户信息存入redis中
        redisCache.setCacheObject("loginAdmin:" + adminId, LoginAdmin);

        //把token和userinfo封装后返回
        AdminInfoVo adminInfoVo = BeanCopyUtils.copyBean(LoginAdmin.getAdmin(), AdminInfoVo.class);
        AdminLoginVo adminLoginVo = new AdminLoginVo(jwt,adminInfoVo);

        return ResponseResult.okResult(adminLoginVo);
    }

    @Override
    public ResponseResult loginByEmail(Admin adminInfo) {
        // 查询邮箱是否存在
        Admin admin = adminMapper.selectOne(new LambdaQueryWrapper<Admin>()
                .eq(Admin::getEmail,adminInfo.getEmail())
                .eq(Admin::getUserType,"0"));
        if (admin == null){
            // TODO:未指定状态码
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_REGISTER);
        }
        // 生成验证码
        String code = RandomCodeUtils.getRandomCode();
        // 验证码存入redis
        CodeDto codeDTO = new CodeDto(code,admin);
        redisCache.setCacheObject("AdminEmail:"+admin.getEmail(),codeDTO,5, TimeUnit.MINUTES);
        // 发送验证码
        emailService.send(new EmailDto(Collections.singletonList(admin.getEmail()),
                "邮箱验证码", content + code));
        // TODO:状态码未指定
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult handleCode(CodeObject object) {
        return codeAuthHandle.AdminCodeAuth(object);
    }

    @Override
    public ResponseResult logout() {
        Long adminId = SecurityUtils.getLoginAdmin().getAdmin().getId();
        redisCache.deleteObject("LoginAdmin:" + adminId);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult loginByPhoneAuthCode(Admin adminInfo) {
        // 查询手机是否存在
        Admin admin = this.findByTelephone(adminInfo);
        if (admin == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_REGISTER);
        }
        try {
            String code = RandomCodeUtils.getRandomCode();
            SendSmsResponse sendSmsResponse = SmsSendUtil.sendSms(admin.getPhoneNumber(), code);
            if(sendSmsResponse.getCode().equals("OK")) {
                // 验证码存入redis，设置过期时间为5分钟
                CodeDto codeDTO = new CodeDto(code,admin);
                redisCache.setCacheObject("AdminTelephone:"+ admin.getPhoneNumber(),codeDTO,5, TimeUnit.MINUTES);
                // 返回201给前端
                return ResponseResult.okResult();
            }else return ResponseResult.errorResult(AppHttpCodeEnum.CODE_SEND_FAIL);
        } catch (ClientException e) {
            throw new RuntimeException("验证码发送出现错误");
        }
    }

    /**
     * 根据手机号查询
     */
    public Admin findByTelephone(Admin admin) {
        LambdaQueryWrapper<Admin> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Admin::getPhoneNumber,admin.getPhoneNumber())
                .eq(Admin::getUserType,"0");
        return adminMapper.selectOne(wrapper);
    }
}
